﻿using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using SG.Lang.Dry.Base;
using SG.Lang.Dry.Mirrors;

namespace SG.Lang.Dry.Persistance
{
    public delegate TElement CreateFunction<in TObj, out TElement>(TObj source, DateTime time)
        where TElement : Element;

    public static class Repository
    {
        public static string BaseDirectory { get; set; }

        public static event EventHandler OnApplicationExit;

        public static IList<TElement> ConvertAndSave<TObj, TElement>(this IList<TObj> @this, DateTime time, CreateFunction<TObj, TElement> create)
            where TElement : Element
        {
            return @this.ToElementList(time, create).Save();
        }

        public static IList<TElement> ToElementList<TObj, TElement>(this IList<TObj> @this, DateTime time, CreateFunction<TObj, TElement> create)
            where TElement : Element
        {
            if (@this == null) throw new ArgumentNullException("this");
            if (create == null) throw new ArgumentNullException("create");

            var count = @this.Count;
            var converted = new TElement[count];
            for (var i = 0; i < count; i++)
                converted[i] = create(@this[i], time);

            return converted;
        }

        public static IList<TElment> Save<TElment>([NotNull] this IList<TElment> @this)
            where TElment : Element
        {
            if (@this == null) throw new ArgumentNullException("this");

            var count = @this.Count;
            var nodeGuids = new Guid[count];

            for (var i = count - 1; i >= 0; i--)
            {
                var itemGuid = @this[i].Guid;
                var next = i == count - 1 ? Guid.Empty : nodeGuids[i + 1];
                var nodeGuid = nodeGuids[i] = Guid.NewGuid();
                var node = new ItemList(ref itemGuid, ref next);
                Repository<ItemList>.Add(ref nodeGuid, ref node);

            }
            return @this;
        }
    }
}
